﻿using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using RuoVea.ExConfig;
using RuoVea.ExDto;
using RuoVea.ExEnum;
using RuoVea.ExLog;
using RuoVea.ExUtil;
using RuoVea.ExWeb;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using UAParser;

namespace RuoVea.ExGlobal
{
    /// <summary>
    /// 全局日志记录 请求日志拦截
    /// RequestActionFilter
    /// </summary>
    public class RequestActionFilter : IAsyncActionFilter
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            bool isDbuge = (Appsettings.app("IsDbug") ?? "false").ToBool();
            if (isDbuge)
            {
                var httpContext = context.HttpContext;
                var httpRequest = httpContext.Request;

                var sw = new Stopwatch();
                sw.Start();
                string actionArguments = string.Empty;
                try { actionArguments = context.ActionArguments.ToJson(); } catch { }

                var actionContext = await next();
                sw.Stop();

                // 判断是否请求成功（没有异常就是请求成功）
                var isRequestSucceed = actionContext.Exception == null;

                var clent = Parser.GetDefault().Parse(httpContext.Request.Headers["User-Agent"]);
                var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
                var descAtt = Attribute.GetCustomAttribute(actionDescriptor.MethodInfo, typeof(DescriptionAttribute)) as DescriptionAttribute;

                string responseResult = string.Empty;
                try
                {
                    if (!actionContext.ExceptionHandled)
                        if (actionContext.Result != null)
                            responseResult = responseResult.IsNullOrWhiteSpace() ? ((Microsoft.AspNetCore.Mvc.ContentResult)actionContext.Result).Content : responseResult;
                        else
                            responseResult = "执行出现错误,请查询错误日志.";
                }
                catch (Exception ex)
                {
                    responseResult = ex.Message;
                }

                var sysOpLog = new
                {
                    Name = descAtt != null ? descAtt.Description : actionDescriptor.ActionName,
                    OpType = 1,
                    Success = isRequestSucceed ? YesOrNot.Y.ToString() : YesOrNot.N.ToString(),
                    //Message = isRequestSucceed ? "成功" : "失败",
                    Ip = httpContext.Connection.RemoteIpAddress?.MapToIPv4()?.ToString(),
                    Location = httpRequest.GetRequestUrlAddress(),
                    Browser = clent.UA.Family + clent.UA.Major,
                    Os = clent.OS.Family + clent.OS.Major,
                    Url = httpRequest.Path,
                    ClassName = context.Controller.ToString(),
                    MethodName = actionDescriptor.ActionName,
                    ReqMethod = httpRequest.Method,
                    Param = actionArguments,
                    //Result = JsonSerializerUtility.Serialize(actionContext.Result),
                    ElapsedTime = sw.ElapsedMilliseconds,
                    OpTime = DateTimeOffset.Now,
                    userId = httpContext.User?.FindFirstValue(ClaimConst.CLAINM_USERID),
                    Account = httpContext.User?.FindFirstValue(ClaimConst.CLAINM_ACCOUNT)
                };

                StringBuilder strInfo = new StringBuilder();
                strInfo.Append("1. 调试: >> 操作时间: " + DateTime.Now + " \r\n");
                strInfo.Append("2. 地址: " + "Method : " + httpRequest.Method + "  URL：" + httpRequest.GetRequestUrlAddress() + "  \r\n");
                strInfo.Append("3. 传入参数: " + actionArguments + " \r\n");
                strInfo.Append("4. 执行结果: " + responseResult + "  \r\n");
                //strInfo.Append("5. IP地址 : " + context.HttpContext.GetRemoteIpAddressToIPv4() + "    \r\n");
                strInfo.Append("-----------------------------------------------------------------------------------------------------------------------------\r\n");

                LogFactory.Debug(strInfo.ToString());
            }
            else
            {
                await next();
            }
        }
    }
}
